package cn.biplam.front.component.view.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map.Entry;

import cn.biplam.common.paramters.TreeParam;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.UserInfo;
import cn.biplam.front.component.data.common.CaptionComp;
import cn.biplam.front.component.data.tree.TreeData;
import cn.biplam.front.component.data.tree.treebase.TreeCallBackImg;
import cn.biplam.front.component.data.tree.treebase.TreeCallBackNew;
import cn.biplam.front.component.data.tree.treebase.TreeDC;
import cn.biplam.front.component.data.tree.treebase.TreeDcCustom;
import cn.biplam.front.component.data.tree.treebase.TreeDcIndex;
import cn.biplam.front.component.data.tree.treebase.TreeDcParent;
import cn.biplam.front.component.data.tree.treebase.Tree_Type.Tree_DC_Type;
import cn.biplam.front.component.data.tree.treebase.Tree_Type.Tree_NodeType_Commen;
import cn.biplam.front.component.data.tree.treebase.Tree_Type.Tree_PicType;
import cn.biplam.front.html.HtmlDiv;
import cn.biplam.front.html.HtmlValue;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.template.control.TreeNew;
import cn.biplam.front.template.control.tree.RightMenu;
import cn.biplam.front.template.control.tree.RightMenuMeta;


/**
 * 树模版基础类，用于支持树vc的使用
 *   <li>设置树的参数信息
 *   <li>获取树的页面对象
 * @author WangSong 2009-10-12下午04:33:01
 * @version 1.0
 */
public class TreeBase {

	/**树 */
	private HtmlWindow tree; 
	/** 树调用的actionId */
	private String aId;
	/** DcTree索引*/
	private ArrayList<Integer> treeIndexs;
	/** DCTree*/
	private KvMap<Integer,TreeDC> treeDcs;
	/** 回调函数，用于返回生成树节点时需要的参数*/
	private KvMap<Integer,TreeCallBackNew> treeCallBacks;
	/** 右键菜单元素容器*/
	private KvMap<Integer,ArrayList<RightMenuMeta>> kvRightMenuMetas;
	/** 有右键菜单的节点操作类型*/
	private ArrayList<String> operatorTypesRm;
	/** 添加的级联操作operatorId*/
	private  KvMap<Integer,String> operatorIdAddNew;
	/** 修改的级联操作operatorId*/
	private KvMap<Integer,String> operatorIdModify;
	/** 删除的级联操作operatorId*/
	private KvMap<Integer,String> operatorIdDelete;
	/**是否显示右键菜单 */
	private boolean showRightMenu = true;
	/**是否显示复选框 */
	private boolean showCheckBox = false;
	/**展开的节点id */
	private String extendNodeId;
	/** 展开节点点击*/
	private boolean extendClick = false;
	/** 树的自定义参数*/
	private String customerParam;
	/** 自定义参数*/
	private String customerParamKey;
	private String customerParamValue;
	/**父容器id */
	private String pcId;
	/**当前节点id */
	private String nodeId;
	/**向下取几级节点 */
	private String levelDown;
	/**当前节点级别 */
	private String nodeLevel;
	/**父亲们是否有弟弟 */
	private String parentsHaveLBrother;
	/**当前节点容器id */
	private String nodeCId;
	/**TreeData集合 Object[0]:TreeData , Object[1]:TreeCallBack */
	private ArrayList<Object[]> alTreeData;
	/**显示的dc，设置过滤器时初始化 */
	private ArrayList<Integer> showObject;
	/**指定显示的dc的参数设置 ，设置过滤器时初始化*/
	private KvMap<String,KvMap<String,String>> showObjectParam;
	/**取取树节点的名称、中文名、说明信息的operatorId容器 KvMap<treeIndex,KvMap<operatorType,operatorId>>*/
	private KvMap<String,KvMap<String,String>> nodeTextOperators;
	/** Dc树编号*/
	private String treeIndex;
	private UserInfo mUser;
	private String sHomeUrl;
	private KvMap<String,String> params;
	/** 右键菜单参数*/
	private KvMap<Integer,ArrayList<String[]>> rightMenuParam;
	/** 节点默认向下展开级别*/
	private KvMap<String,String> defualtLevelDown;
	/** dc的参数存储*/
	private KvMap<Integer,String[]> dcParmas;
	/** 单棵树是否显示虚根 true:显示 false:不显示  默认:false*/
	private boolean showVirRoot = false;
	/** 虚根是否展开*/
	private boolean isVirExtend = false;
	/** 使用的子树,设置过滤后的子树字符串,以"#"分割*/
	private String treeIndexUsed;
	/**当前节点是否有哥哥 */
	private String haveBrother;
	/**当前节点是否有弟弟 */
	private String haveLBrother;
	/** 过滤数据操作id*/
	private String filterOperatorId;
	/**是否显示加号减号 */
	private boolean showPicExtend = false;
	/**图片设置类*/
	private KvMap<Integer,TreeCallBackImg> treeCallBackImgs;

	/**
	 * 构造函数
	 *   只传树的vc的actionId，默认显示根节点(节点id为-1的节点)以下(不包括-1)的节点信息
	 * @param aId 树的vc的actionId
	 */
	public TreeBase(String aId){
		this.aId = aId;
		treeIndexs = new ArrayList<Integer>();
		treeDcs = new KvMap<Integer, TreeDC>();
		treeCallBacks = new KvMap<Integer, TreeCallBackNew>();
		kvRightMenuMetas = new KvMap<Integer, ArrayList<RightMenuMeta>>();
		operatorTypesRm = new ArrayList<String>();
		operatorIdAddNew = new KvMap<Integer, String>();
		operatorIdModify = new KvMap<Integer, String>();
		operatorIdDelete = new KvMap<Integer, String>();
		alTreeData = new ArrayList<Object[]>();
		dcParmas = new KvMap<Integer, String[]>();
		treeCallBackImgs = new KvMap<Integer, TreeCallBackImg>();
	}

	/**
	 * 设置树DC-父子表、自定义、索引表
	 * @param treeDc 树的DC
	 * @param callback 用于返回生成树节点时需要的参数
	 * @throws ErrorMessage
	 */
	public void putTreeDc(int treeIndex,
			TreeDC treeDc,
			TreeCallBackNew callback) throws ErrorMessage{
		/**保存dc的编号*/
		treeIndexs.add(treeIndex);
		/**保存dcTree*/
		treeDcs.put(treeIndex, treeDc);

		treeCallBacks.put(treeIndex, callback);
		/**保存dcTree的参数*/
		dcParmas.put(treeIndex, new String[]{treeDc.getOperatorId(),
				treeDc.getRowId(),
				treeDc.getField()});
		getTreeIndexFilter(treeDc);
	}

	/**
	 * 设置右键菜单项(根据树的编号和节点类型来设置右键菜单项)
	 * @param treeIndex 树编号
	 * @param nodeType 可用此右键菜单项的节点类型
	 * @param actionId 右键菜单项的actionId
	 * @param text 右键菜单项的名称，此处用的是captionId
	 * @throws ErrorMessage
	 */
	public void putRightMenuItem(int treeIndex,
			Tree_NodeType_Commen nodeType,
			String actionId,
			String text) throws ErrorMessage{
		putRightMenuItem(treeIndex, nodeType.toString(), actionId, text,null);
	}

	/**
	 * 设置右键菜单项(根据树的编号和节点类型来设置右键菜单项)
	 * @param treeIndex 树编号
	 * @param operatorType 可用此右键菜单项的节点类型
	 * @param actionId 右键菜单项的actionId
	 * @param text 右键菜单项的名称，此处用的是captionId
	 * @param showCode 显示此右键选项的代码,目前对应索引树的node_type字段
	 * @throws ErrorMessage
	 */
	public void putRightMenuItem(int treeIndex,
			Tree_NodeType_Commen operatorType,
			String actionId,
			String text,
			String showCode) throws ErrorMessage{
		putRightMenuItem(treeIndex, operatorType.toString(), actionId, text,showCode);
	}

	/**
	 * 设置右键菜单项(根据树的编号和节点类型来设置右键菜单项)
	 * @param treeIndex 树编号
	 * @param nodeType 可用此右键菜单项的节点类型
	 * @param actionId 右键菜单项的actionId
	 * @param text 右键菜单项的名称，此处用的是captionId
	 * @param showCode 显示此右键选项的代码,目前对应索引树的node_desc字段
	 * @throws ErrorMessage
	 */
	public void putRightMenuItem(int treeIndex,
			String nodeType,
			String actionId,
			String text,
			String showCode) throws ErrorMessage{
		if(!operatorTypesRm.contains(nodeType)){
			operatorTypesRm.add(nodeType);
		}
		ArrayList<RightMenuMeta> rightMenuMetas = null;
		if(kvRightMenuMetas.getByKey(treeIndex)!=null){
			rightMenuMetas = kvRightMenuMetas.getByKey(treeIndex);
		}else{
			rightMenuMetas = new ArrayList<RightMenuMeta>();
			kvRightMenuMetas.put(treeIndex, rightMenuMetas);
		}
		/**检查参数*/
		TOOLS.checkNull(actionId, "\n\t TreeeDcIndex actionId");
		TOOLS.checkNull(text, "\n\t TreeeDcIndex text");
		if(rightMenuMetas==null){
			rightMenuMetas = new ArrayList<RightMenuMeta>();
		}
		/**右键参数保存*/
		RightMenuMeta rmm = new RightMenuMeta();
		rmm.setActionId(actionId);
		rmm.setText(text);
		rmm.setOperatorType(nodeType);
		rmm.setShowCode(showCode);
		rightMenuMetas.add(rmm);
	}

	/**
	 * 设置右键添加的级联操作operatorId<br>
	 *  DataFilter中包含的参数有 :<br>
	 *    父节点id:TreeParam.NODE_ID<br>
	 *    父节点真实id:TreeParam.NODE_REAL_ID<br>
	 *    父节点操作类型:TreeParam.OPERATOR_TYPE<br>
	 *    父节点类型:TreeParam.NODE_TYPE(子树索引编号)<br>
	 *    索引表名称:TreeParam.TABLE_NAME<br>
	 *    新节点录入名称:TreeParam.NAME<br>
	 *    新节点录入描述:TreeParam.DESC<br>
	 * @param treeIndex 子树索引编号
	 * @param operatorId  级联操作的operatorId
	 */
	public void setExtraOperatorIdAdd(int treeIndex,
			String operatorId) throws ErrorMessage{
		operatorIdAddNew.put(treeIndex, operatorId);
	}

	/**
	 * 设置右键修改的级联操作operatorId<br>
	 *  DataFilter中包含的参数有 :<br>
	 *    节点id:TreeParam.NODE_ID<br>
	 *    节点真实id:TreeParam.NODE_REAL_ID<br>
	 *    节点操作类型:TreeParam.OPERATOR_TYPE<br>
	 *    节点类型:TreeParam.NODE_TYPE(子树索引编号)<br>
	 *    索引表名称:TreeParam.TABLE_NAME<br>
	 *    节点录入名称:TreeParam.NAME<br>
	 *    节点录入描述:TreeParam.DESC<br>
	 * @param treeIndex 树编号
	 * @param operatorId 修改的级联操作operatorId
	 */
	public void setExtraOperatorIdModify(int treeIndex,
			String operatorId) throws ErrorMessage{
		operatorIdModify.put(treeIndex, operatorId);
	}

	/**
	 * 设置右键删除的级联操作operatorId<br>
	 *  DataFilter中包含的参数有 :<br>
	 *    节点id:TreeParam.NODE_ID<br>
	 *    节点真实id:TreeParam.NODE_REAL_ID<br>
	 *    节点操作类型:TreeParam.OPERATOR_TYPE<br>
	 *    节点类型:TreeParam.NODE_TYPE(子树索引编号)<br>
	 *    索引表名称:TreeParam.TABLE_NAME<br>
	 * @param treeIndex 树编号
	 * @param operatorId 修改的级联操作operatorId
	 */
	public void setExtraOperatorIdDelete(int treeIndex,
			String operatorId) throws ErrorMessage{
		operatorIdDelete.put(treeIndex, operatorId);
	}

	/**
	 * 设置取树"根主题"节点的名称、中文名、说明信息的operatorId
	 * @param treeIndex 树索引
	 * @param operatorId 通过此id查询树节点的名称(Result第2列是名称)
	 * @throws ErrorMessage 
	 */
	public void setRootThemeOperatorId(int treeIndex,String operatorId) throws ErrorMessage{
		setNodeTextOperatorId(TOOLS.intToString(treeIndex),Tree_NodeType_Commen.RootTheme.toString(), operatorId);
	}

	/**
	 * 设置取树"子主题"节点的名称、中文名、说明信息的operatorId
	 * @param treeIndex 树索引
	 * @param operatorId 通过此id查询树节点的名称(Result第2列是名称)
	 * @throws ErrorMessage 
	 */
	public void setSubThemeOperatorId(int treeIndex,String operatorId) throws ErrorMessage{
		setNodeTextOperatorId(TOOLS.intToString(treeIndex),Tree_NodeType_Commen.SubTheme.toString(), operatorId);
	}

	/**
	 * 设置取树"叶子节点"的名称、中文名、说明信息的operatorId
	 * @param treeIndex 树索引
	 * @param nodeType 可用此右键菜单项的节点类型
	 * @param operatorId 通过此id查询树节点的名称(Result第2列是名称)
	 * @throws ErrorMessage 
	 */
	public void setNodeLeafOperatorId(int treeIndex,String operatorId) throws ErrorMessage{
		setNodeTextOperatorId(TOOLS.intToString(treeIndex),Tree_NodeType_Commen.Leaf.toString(), operatorId);
	}

	/**
	 * 设置右键菜单是否显示
	 * @param show  true显示 false不显示
	 */
	public void setRightMenu(boolean show){
		showRightMenu = show;
	}

	/**
	 * 设置是否显示复选框(复选框应用时提交树的容器id,提交后用TreeParam.getCheckBoxId来取checkbox提交后的key值)
	 * @param show true显示 false不显示
	 */
	public void setShowCheckBox(boolean show){
		showCheckBox = show;
	}

	/**
	 * 设置需要展开的节点的Id
	 * @param extendNodeId 需要展开的节点Id
	 */
	public void setExtendNodeID(String extendNodeId){
		setExtendNodeId(extendNodeId, false);
	}

	/**
	 * 设置展开节点的Id
	 * @param extendNodeId
	 * @param click 是否点击  true:点击  false:不点击，只标识背景颜色
	 */
	public void setExtendNodeId(String extendNodeId,boolean click) {
		this.extendNodeId = extendNodeId;
		this.extendClick = click;
	}

	/**
	 * 设置树的自定义参数,在树展开时出现在params容器中<BR>
	 * （取时用params.getByKey(".customerParam")）
	 * @param customerParam
	 * @throws ErrorMessage 
	 */
	public void setCustomerParam(String customerParam) throws ErrorMessage{
		checkString(customerParam);
		this.customerParam = customerParam;
	}

	/**
	 * 设置树的自定义参数(key和value方式),在树展开时出现在params容器中<BR>
	 * 只能有一个
	 * @param key 参数名称
	 * @param value 参数值
	 * @throws ErrorMessage 
	 */
	public void setCustomerParam(String key,String value) throws ErrorMessage{
		if(customerParamKey!=null){
			throw new ErrorMessage("CustomerParam is only one!");
		}
		TOOLS.checkNull(key, "TreeBase setCustomerParam(String key,String value) error,key");
		checkString(key);
		checkString(value);
		customerParamKey = key;
		customerParamValue = value;
	}

	/**
	 *  树是否显示表中的虚根
	 * @param showVirRoot 树是否显示表中的虚根 true:显示表中虚根,不显示外部设置的虚构 fasle:不显示表中虚根  默认:false
	 */
	public void setShowVirRoot(boolean showVirRoot){
		setShowVirRoot(showVirRoot, false);
	}

	/**
	 *  树是否显示表中的虚根
	 * @param showVirRoot 树是否显示表中的虚根 true:显示表中虚根,不显示外部设置的虚构 fasle:不显示表中虚根  默认:false
	 * @param isVirExtend 虚根是否展开 true:展开 fasle:不展开  默认:false
	 */
	public void setShowVirRoot(boolean showVirRoot,boolean isVirExtend){
		this.showVirRoot = showVirRoot;
		this.isVirExtend = isVirExtend;
	}

	/**
	 * 设置树的节点图片
	 * @param treeIndex 树编号
	 * @param picType 图片类型
	 * @throws ErrorMessage 
	 */
	public void setPic(int treeIndex,Tree_PicType picType) throws ErrorMessage{
		setPic(treeIndex, TreeCallBackImg.getInstanct(picType));
	}

	/**
	 * 设置树的节点图片
	 * @param treeIndex 树编号
	 * @param callBackPic 图片设置类
	 * @throws ErrorMessage 
	 */
	public void setPic(int treeIndex,TreeCallBackImg callBackPic) throws ErrorMessage{
		if(treeCallBackImgs==null){
			treeCallBackImgs = new KvMap<Integer, TreeCallBackImg>();
		}
		treeCallBackImgs.put(treeIndex, callBackPic); 
	}

	/**
	 * 设置子树的自定义参数
	 * @param treeIndex 树索引
	 * @param key 参数名称
	 * @param value 参数值
	 * @throws ErrorMessage 
	 */
	public void putSubTreeParam(int treeIndex,String key,String value) throws ErrorMessage{
		if(!TOOLS.StringIsEmpty(value)){
			checkString(key);
			checkString(value);
			ArrayList<String[]> alParam = null;
			String[] param = new String[2];
			if(rightMenuParam==null){
				rightMenuParam = new KvMap<Integer, ArrayList<String[]>>();
			}
			if(rightMenuParam.getByKey(treeIndex)!=null){
				alParam = rightMenuParam.getByKey(treeIndex);
			}else{
				alParam = new ArrayList<String[]>();
			}
			param[0] = key;
			param[1] = value;
			alParam.add(param);
			rightMenuParam.put(treeIndex, alParam);
		}
	}

	/**
	 * 页面直接调用接口(用于非Ajx请求时,获取页面对象)
	 * 第一次生成树时调用
	 * @param mUser 用户信息
	 * @param sHomeUrl 系统路径
	 * @param pcId 调用者的容器id(此参数为4位,否则做截位补齐处理)
	 * @return HtmlWindow 显示树的HtmlWindow
	 * @throws ErrorMessage
	 */
	public HtmlWindow get(UserInfo mUser, 
			String sHomeUrl,
			String pcId) throws ErrorMessage {
		this.mUser = mUser;
		this.sHomeUrl = sHomeUrl;
		this.pcId = TOOLS.stringClip(pcId, 4);

		/**对pcId参数做处理*/
		/**获取树*/
		getTree();
		return tree;
	}


	/**
	 * 用于Ajx请求时,获取页面对象
	 * @param mUser 用户信息
	 * @param sHomeUrl 系统路径
	 * @param param 页面传来的参数列表
	 * @return HtmlWindow 显示树的HtmlWindow
	 * @throws ErrorMessage
	 */
	public HtmlWindow ajxGet(UserInfo mUser, 
			String sHomeUrl,
			KvMap<String,String> params) throws ErrorMessage {
		this.mUser = mUser;
		this.sHomeUrl = sHomeUrl;
		this.params = params;
		if(customerParam==null){
			customerParam = params.getByKey("customerParam");
		}
		if("Y".equals(this.params.getByKey("refresh"))){//树的增删改刷新
			this._setRefreshParam();
			getTree();
			return tree;
		}else{
			return this.get(this.mUser,this.sHomeUrl, this.params);	
		}	
	}

	/**
	 * 上层容器ajx调用时的调用接口
	 * @param user     用户信息
	 * @param homeUrl  系统路径
	 * @param params   ajx的参数
	 * @return HtmlWindow
	 * @throws ErrorMessage
	 */
	private HtmlWindow get(UserInfo user, String homeUrl,KvMap<String,String> params) throws ErrorMessage{
		this.mUser = user;
		this.sHomeUrl = homeUrl;
		this.params = params;
		/**为getTree准备所需的数据(userId,nodeId,nodeLevel,levelDown,nodeType)从ajx的params中取*/
		this.setParamAjx();
		/**设置过滤器、左键、右键、复选框、需要展开节点等信息*/
		_setAjxInfo();
		getTree();
		return tree;
	}

	/**
	 * 取树
	 * @throws ErrorMessage
	 */
	private void getTree() throws ErrorMessage{
		/**初始化树的模版*/
		TreeNew mTree = new TreeNew(pcId,
				aId,
				alTreeData,
				sHomeUrl);
		/**根据dc取树的TreeData。第一次生成树节点时用get()，TreeData是根据过滤器的设置来取。
		     以后树节点的展开是用ajxGet(), 此时TreeData是根据节点的属性来判断用哪个Dc,然后设置过滤器*/
		this.setTreeDatas(mTree);
		clearParams();
		/**设置显示右键菜单*/
		if(showRightMenu){
			getRightMenu(mTree);
		}
		/**设置是否显示复选框*/
		mTree.setCheckBox(showCheckBox);
		/**设置展开节点Id*/
		if(extendNodeId!=null){
			mTree.setExtendNodeId(extendNodeId,extendClick);
		}
		/**设置树的展开节点信息*/
		if(nodeCId!=null){
			mTree.setNodeContainerId(nodeCId);
		}
		/**设置自定义参数*/
		mTree.setCustomerParam(customerParam);
		mTree.setCustomerParam(customerParamKey,customerParamValue);
		/**设置树节点的名称、中文名、说明的operatorId*/
		if(nodeTextOperators!=null){
			mTree.setNodeTextOperatorId(nodeTextOperators);
		}
		/**设置默认向下展开级别*/
		if(defualtLevelDown!=null){
			mTree.setDefaultLevelDown(defualtLevelDown);
		}
		/**设置dc参数*/
		mTree.setDcParams(dcParmas);
		/**设置单棵树是否显示虚根*/
		mTree.setShowVirRoot(showVirRoot);
		mTree.setIsVirRootExtend(this.isVirExtend);
		/**设置使用过的子树索引,刷新时用*/
		mTree.setUsedTreeIndex(treeIndexUsed);
		if(rightMenuParam!=null){
			mTree.setRightMenuParam(rightMenuParam);
		}
		//设置索引树过滤的operatorId
		mTree.setFilterOperatorId(filterOperatorId);
		mTree.showPicExtend(showPicExtend);
		mTree.setTreeIndexRefresh(treeIndex);

		this.tree = mTree.get();
	}

	/**
	 * 设置树的数据信息
	 * @param mTree 树模版对象
	 * @throws ErrorMessage 
	 */
	private void setTreeDatas(TreeNew mTree) throws ErrorMessage{
		/**从DC中取出需要的treeData和callBack,放到ArrayList<Object[]>中，设置到树的模版中*/
		if(this.showObject!=null){
			/**显示设置的dcTree*/
			this.setDc(mTree);
		}else{
			/**显示全部dc*/
			setAllDcTree(mTree);
		}
	}

	/**
	 * 显示已经设置的dc
	 * @throws ErrorMessage 
	 */
	private void setDc(TreeNew mTree) throws ErrorMessage{
		int showTreeIndex;
		for(int i=0;i<showObject.size();i++){
			showTreeIndex = showObject.get(i);
			setDcSwitch(showTreeIndex,mTree);
		}
	}

	/**
	 * 设置显示的所有树
	 */
	private void setAllDcTree(TreeNew mTree) throws ErrorMessage{
		for(int treeIndex:treeIndexs){
			setDcSwitch(treeIndex,mTree);
		}

	}

	/**
	 * 设置显示的dc分支
	 * @param nodeType 树的节点类型
	 * @param mTree 树模版对象
	 * @throws ErrorMessage
	 */
	private void setDcSwitch(int treeIndex,TreeNew mTree) throws ErrorMessage{
		//根据设置的DC的参数来初始化nodeId, nodeLevel, levelDown, showCurrentNode等信息
		Object[] obj = new Object[2];
		String nodeId = this.getSetFilterParam(TOOLS.intToString(treeIndex), "nodeId", this.nodeId);
		String nodeLevel = this.getSetFilterParam(TOOLS.intToString(treeIndex), "nodeLevel", this.nodeLevel);
		String levelDown = this.getSetFilterParam(TOOLS.intToString(treeIndex), "levelDown", this.levelDown);
		String parentsHaveLBrother = this.getSetFilterParam(TOOLS.intToString(treeIndex), "parentsHaveLBrother", this.parentsHaveLBrother);
		setDcTree(treeIndex, nodeId, nodeLevel, levelDown, parentsHaveLBrother, obj);
		this.alTreeData.add(obj);
	}

	/**
	 * 初始化dc并且返回树模版所需树的数据和回调函数
	 * @param treeIndex 树编号
	 * @param nodeId 展开的节点id
	 * @param nodeLevel 展开的节点级别
	 * @param levelDown 向下显示几级
	 * @param parentsHaveLBrother 父亲是否弟弟
	 * @param obj 参数对象，存储TreeData和TreeCallBack
	 * @throws ErrorMessage
	 */
	private void setDcTree(int treeIndex,
			String nodeId,
			String nodeLevel,
			String levelDown,
			String parentsHaveLBrother,
			Object[] obj) throws ErrorMessage {
		TreeDC td = treeDcs.getByKey(treeIndex);
		setTreeIndexFilter(td);
		if(nodeId!=null && nodeLevel!=null && td!=null){
			//展开操作
			String dcParam = params.getByKey("dcParams");
			/**从ajx来的展开请求或刷新请求，需要重新定义Dc*/
			if(Tree_DC_Type.TreeIndex.equals(td.getType())){
				setTreeDcIndex(td, nodeId, nodeLevel, levelDown, haveBrother, haveLBrother, parentsHaveLBrother);
			}else if(Tree_DC_Type.TreeParent.equals(td.getType())){
				if(dcParam!=null && !"".equals(dcParam.trim())){
					/**0:operatorId,1:rowid,2:fieldMap*/
					String[] dcParamArr = dcParam.split("#");
					setTreeDcParent(td, nodeId, nodeLevel, levelDown, haveBrother, haveLBrother, parentsHaveLBrother, dcParamArr);
				}
			}else if(Tree_DC_Type.TreeCustomer.equals(td.getType())){
				if(dcParam!=null && !"".equals(dcParam.trim())){
					/**0:operatorId,1:rowid,2:fieldMap*/
					String[] dcParamArr = dcParam.split("#");
					td = setTreeDcCustom(td, dcParamArr, nodeId, levelDown);
				}
			}
		}else if(params!=null && "Y".equals(params.getByKey("refresh"))){
			//刷新操作
			if(this.dcParmas!=null && this.dcParmas.getByKey(treeIndex)!=null){
				/**0:operatorId,1:rowid,2:fieldMap*/
				String[] dcParamArr = this.dcParmas.getByKey(treeIndex);
				if(Tree_DC_Type.TreeParent.equals(td.getType())){
					setTreeDcParent(td, nodeId, nodeLevel, levelDown, haveBrother, haveLBrother, parentsHaveLBrother, dcParamArr);
				}else if(Tree_DC_Type.TreeCustomer.equals(td.getType())){
					td = setTreeDcCustom(td, dcParamArr, nodeId, levelDown);
				}
			}
		}

		if(showVirRoot){
			if(TOOLS.stringToInt(nodeLevel)>=1){
				showVirRoot = false;
			}
			td.setVirtualNodeVisiable(showVirRoot);
		}
		if(td==null){
			throw new ErrorMessage("treeIndex is not found:"+treeIndex);
		}
		/**设置DC的参数，针对父子树和自定义树*/
		setDcParam(td, treeIndex);
		/**设置树的编号到treeData中去,生成树时用*/
		TreeData treeData =  td.get();
		treeData.setTreeIndex(TOOLS.intToString(treeIndex));
		/**设置Dc和Callback数组容器*/
		obj[0] = treeData;
		/**保存callback*/
		TreeCallBackNew callback = treeCallBacks.getByKey(treeIndex);
		if(treeCallBackImgs!=null && treeCallBackImgs.getByKey(treeIndex)!=null){
			callback.setPic(treeCallBackImgs.getByKey(treeIndex));
		}
		obj[1] = callback;
		/**设置子树应用字符串*/
		if(treeIndexUsed == null){
			treeIndexUsed = TOOLS.intToString(treeIndex);
		}else{
			treeIndexUsed = treeIndexUsed +"_"+TOOLS.intToString(treeIndex);
		}
	}

	/**
	 *  设置自定义树DC
	 */
	private TreeDC setTreeDcCustom(TreeDC td,
			String[] dcParamArr,String nodeId,String levelDown){
		TreeDcCustom td1 = (TreeDcCustom)td;
		td1.setOperatorId(dcParamArr[0]);
		td1.setRowId(dcParamArr[1]);
		td1.setNodeId(nodeId);
		//整棵树刷新时不用设置leveldown,用树默认的
		if(!"Y".equals(this.params.getByKey("refresh"))){
			td1.setSetLevelDown(levelDown);
		}
		return td1;
	}

	/**
	 *  设置索引树DC参数
	 */
	private void setTreeDcIndex(TreeDC td,
			String nodeId,String nodeLevel
			,String levelDown, 
			String haveBrother, 
			String haveLBrother,String parentsHaveLBrother){
		TreeDcIndex td1 = (TreeDcIndex)td;
		td1.setNodeId(nodeId);
		td1.setNodeLevel(nodeLevel);
		//整棵树刷新时不用设置leveldown,用树默认的
		if(!"Y".equals(this.params.getByKey("refresh"))){
			td1.setLevelDown(levelDown);
		}
		td1.setHaveBrother(haveBrother);
		td1.setHaveLBrother(haveLBrother);
		td1.setParentsHaveLBrother(parentsHaveLBrother);
	}

	/**
	 *  设置父子树DC参数
	 */
	private void setTreeDcParent(TreeDC td,
			String nodeId,String nodeLevel
			,String levelDown, 
			String haveBrother, 
			String haveLBrother,
			String parentsHaveLBrother,
			String[] dcParamArr){
		TreeDcParent tdp = (TreeDcParent)td;
		//设置树基本参数
		tdp.setNodeId(nodeId);
		tdp.setNodeLevel(nodeLevel);
		//整棵树刷新时不用设置leveldown,用树默认的
		if(!"Y".equals(this.params.getByKey("refresh"))){
			tdp.setLevelDown(levelDown);
		}
		tdp.setHaveBrother(haveBrother);
		tdp.setHaveLBrother(haveLBrother);
		tdp.setParentsHaveLBrother(parentsHaveLBrother);
		//设置映射字段名称 /**0:operatorId,1:rowid,2:fieldMap*/
		String[] fieldMap = dcParamArr[2].split(">");
		tdp.setMappingNodeId(fieldMap[0]);
		tdp.setMappingNodeName(fieldMap[1]);
		tdp.setMappingNodeParent(fieldMap[2]);
		tdp.setMappingOperatorType(fieldMap[4]);
		tdp.setMappingRealId(fieldMap[5]);
	}

	/**
	 * 设置DC的参数，针对父子树和自定义树
	 *   参数存储器为一个字符串数组，存储的参数依次为 
	 *     operatorId(操作id),
	 *     rowid(operator生成sql需要的参数),
	 *     field字符串(父子树使用,operator生成sql中的字段和树的基础字段的映射关系)
	 * @param td 树dc对象,提供operatorId,rowid和field字符串
	 * @param treeIndex 树编号
	 * @throws ErrorMessage 
	 */
	private void setDcParam(TreeDC td,int treeIndex) throws ErrorMessage{
		/**从现有参数列表中取参数数组*/
		String[] dcParam = dcParmas.getByKey(treeIndex);
		/**如果取得的参数数组为空,新建数组对象*/
		if(dcParam==null){
			dcParam = new String[3];
		}
		/**从dc中取参数*/
		if(td!=null){
			dcParam[0] = td.getOperatorId();
			dcParam[1] = td.getRowId();
			dcParam[2] = td.getField();
		}
		/**重新设置到参数容器中取*/
		dcParmas.put(treeIndex,dcParam);
	}

	/**
	 * ajx的树请求设置过滤器
	 * @throws ErrorMessage
	 */
	private void _setAjxInfo() throws ErrorMessage{
		/**设置过滤器，按树的编号进行过滤*/
		this.setFilter(treeIndex, nodeId, nodeLevel, levelDown);
		/**设置右键是否显示*/
		this.showRightMenu = Boolean.parseBoolean(this.params.getByKey("srm"));
		/**设置是否显示复选框*/
		this.showCheckBox = Boolean.parseBoolean(this.params.getByKey("sck"));
		/**设置callback*/
		setTreeCallBack();
	}

	/**
	 * ajx请求时,设置callback信息（展开树）
	 * @throws ErrorMessage 
	 */
	private void setTreeCallBack() throws ErrorMessage{
		if(params!=null){

			String aids = params.getByKey("aId");
			String tids = params.getByKey("tId");

			setTreeCallBack(treeIndex, aids, tids);
		}
	}

	/**
	 * ajx请求时,设置callback信息(刷新树)
	 * @throws ErrorMessage 
	 */
	private void setRefreshTreeCallBack() throws ErrorMessage{
		if(this.params.getByKey("callback")!=null){
			//分割多个callback
			String[] arrCallbacks = this.params.getByKey("callback").split("~");
			/**以树索引为第一个参数的字符串数组*/
			String[] arrcallback = null;
			String aids = null;
			String tids = null;
			for(int i=0;i<arrCallbacks.length;i++){
				arrcallback = arrCallbacks[i].split(":");
				if(arrcallback.length >= 7){
					if(arrcallback[1]!=null && !"".equals(arrcallback[1].trim())
							&& arrcallback[2]!=null && !"".equals(arrcallback[2].trim())){
						aids = arrcallback[2];
						tids = arrcallback[1];
						setTreeCallBack(arrcallback[0], aids, tids);
					}
				}else{
					throw new ErrorMessage("TreeBase setRefreshTreeCallBack() Error,callback param is not correct");
				}
			}
		}
	}

	/**
	 * ajx请求时，设置Treecallback
	 * @param treeIndex 树编号
	 * @param aids Dc所有左键的行为id(格式为:operatorType1#actionId1<operatorType2#actionId2)
	 * @param tids Dc左键的目标容器id(格式为:operatorType1#targetId1<operatorType2#targetId2)
	 * @throws ErrorMessage
	 */
	private void setTreeCallBack(String treeIndex,String aids,String tids) throws ErrorMessage{
		String[] aidArr = null;
		String[] tidArr = null;
		String[] _aidArr = null;
		String[] _tidArr = null;

		if(!TOOLS.StringIsEmpty(aids) && !TOOLS.StringIsEmpty(tids)){
			TreeCallBackNew callBack = treeCallBacks.getByKey(TOOLS.stringToInt(treeIndex));
			aidArr = aids.split("<");
			tidArr = tids.split("<");
			for(int i=0;i<aidArr.length;i++){
				_aidArr = aidArr[i].split("#");
				_tidArr = tidArr[i].split("#");
				if(_aidArr.length>=2 && _tidArr.length>=2){
					callBack.putLeftClick(_aidArr[0], _aidArr[1], _tidArr[1]);
				}
			}
			callBack.setPic(this.treeCallBackImgs.getByKey(TOOLS.stringToInt(treeIndex)));
		}
	}

	/**
	 * 取得设置过滤器时设置的参数信息，如果没有在设置过滤器时设置此参数，则用默认值
	 * @param nodeType  节点类型
	 * @param paramName  参数名称
	 * @param defaultValue  参数默认值
	 * @return String
	 * @throws ErrorMessage 
	 */
	private String getSetFilterParam(String nodeType,String paramName,String defaultValue) throws ErrorMessage{
		String paramValue = null;

		if(this.showObjectParam!=null){
			//取参数集合
			KvMap<String,String> params = this.showObjectParam.getByKey(nodeType);
			if(params!=null){
				//取指定参数
				paramValue = params.getByKey(paramName);
			}
		}

		//如果没有在设置过滤器时设置此参数，则用默认值
		if(paramValue == null || "".equals(paramValue.trim())){
			paramValue = defaultValue;
		}
		return paramValue;
	}

	/**
	 * 设置显示哪些DC(以树编号进行过滤，设置的树编号显示),如果不设置则不进行过滤，全部显示
	 * @param treeIndex DcTree编号
	 * @param nodeId 展开节点id
	 * @param nodeLevel 展开节点级别
	 * @param levelDown 向下取几级
	 * @throws ErrorMessage
	 */
	private void setFilter(String treeIndex,
			String nodeId,
			String nodeLevel,
			String levelDown) throws ErrorMessage{
		if(showObjectParam==null){
			showObjectParam = new KvMap<String, KvMap<String,String>>();
		}
		KvMap<String,String> kvParam = new KvMap<String, String>();
		setParam(kvParam, "nodeId",nodeId);
		setParam(kvParam, "nodeLevel",nodeLevel);
		setParam(kvParam, "levelDown",levelDown);
		setFilter(treeIndex);
		showObjectParam.put(treeIndex, kvParam);
	}

	/**
	 * 设置显示哪些DC(以树编号进行过滤，设置的树编号显示),如果不设置则不进行过滤，全部显示
	 * @param treeIndex DcTree编号
	 * @throws ErrorMessage 
	 */
	private void setFilter(String treeIndex) throws ErrorMessage{
		//在VC中增加DC的过滤器，选择显示哪些DC
		if(this.showObject==null){
			this.showObject = new ArrayList<Integer>();
		}
		this.showObject.add(TOOLS.stringToInt(treeIndex));
	}


	/**
	 * 设置参数，如果参数不为空则设置参数
	 * @param kvParam
	 * @param param
	 * @param paramValue
	 * @throws ErrorMessage
	 */
	private void setParam(KvMap<String,String> kvParam,
			String param,
			String paramValue) throws ErrorMessage{
		if(paramValue!=null && !paramValue.equals("")){
			kvParam.put(param, paramValue);
		}
	}

	/**
	 * ajx请求时，从params中取页面传来的参数
	 * @throws ErrorMessage 
	 */
	private void setParamAjx() throws ErrorMessage{
		/**nodeId格式为cId,nodeId,operatorType,nodeType,nodeLevel,是否有哥哥,弟弟,父亲们是否有弟弟*/
		String [] nodeIdParams = this.splitParam(this.params.getByKey("nodeId"));
		nodeId = nodeIdParams[1];
		nodeLevel = nodeIdParams[4];
		/**通过ajx来取树,是展开节点取当前节点的下级,此时只向下取一级*/
		levelDown = "1";
		//树刷新时有展开多级的情况
		if(!TOOLS.StringIsEmpty(params.getByKey("rlevelDown"))){
			levelDown = params.getByKey("rlevelDown");
		}
		if(nodeIdParams.length<9){//根节点的次参数是空的
			parentsHaveLBrother = null;
		}else{
			parentsHaveLBrother = nodeIdParams[8];
		}
		pcId = nodeIdParams[0].substring(0,4);
		/**用于判断节点是哪个业务模型对象类型，从而取相应的TreeData*/
		treeIndex = nodeIdParams[2];
		this.haveBrother = nodeIdParams[5];
		this.haveLBrother = nodeIdParams[6];
		/**需要展开的节点id*/
		extendNodeId = this.params.getByKey("extendId");
		extendClick = TOOLS.stringToBoolean(params.getByKey("extendClick"));
		nodeCId = this.params.getByKey("nodeId");
		this.filterOperatorId = this.params.getByKey(TreeParam.TreeIndexFilterOperatorId);
		String showAdd = params.getByKey("showAdd");
		if("Y".equals(showAdd)){
			showPicExtend = true;
		}else{
			showPicExtend = false;
		}
	}

	/**
	 * 分解参数信息
	 * @param params
	 * @return String[]
	 * @throws ErrorMessage
	 */
	private String[] splitParam(String params) throws ErrorMessage{
		if(params==null || "".equals(params.trim())){
			throw new ErrorMessage("params is null");
		}
		String [] nodeIdParams = params.split("#");
		if(nodeIdParams.length<7){
			throw new ErrorMessage("params is not correct:"+params);
		}
		return nodeIdParams;
	}

	/**
	 * 设置树的刷新时的参数准备
	 * @throws ErrorMessage 
	 */
	private void _setRefreshParam() throws ErrorMessage{
		this.pcId = this.params.getByKey("pcid");
		this.nodeCId = this.params.getByKey("nodeId");
		this.filterOperatorId = this.params.getByKey(TreeParam.TreeIndexFilterOperatorId);
		this.treeIndex = this.params.getByKey("tIndex");
		/**设置callback*/
		setRefreshTreeCallBack();
		/**设置过滤器*/
		this._setRefreshFilter();
		/**设置Dc树的参数*/
		_setRefreshDcParam();
		/**设置是否显示右键*/
		this._setRefreshShowRightMenu();
		/**设置是否显示checkBox*/
		this._setRefreshShowCheckBox();
		/**设置展开节点*/
		this._setsetRefreshExtendNode();
		/**设置是否显示虚根*/
		_setVirRoot();
		/**设置树取节点文本的operatorId*/
		_setRefreshTextOpreatorIdParam();
		/**设置右键自定义参数*/
		_setRefreshRmParam();

	}

	/**
	 * 设置树刷新时的过滤器信息
	 * @throws ErrorMessage 
	 */
	private void _setRefreshFilter() throws ErrorMessage{
		String filter = this.params.getByKey("filter");
		if(filter!=null){
			//分割多个过滤器
			String[] arrFilters = filter.split("~");
			String[] arrFilter = null;
			for(int i=0;i<arrFilters.length;i++){
				arrFilter = arrFilters[i].split(":");
				if(arrFilter.length == 2){
					this.setFilter(arrFilter[0],
							arrFilter[1], nodeLevel, levelDown);
				}else if(arrFilter.length >= 3){
					this.setFilter(arrFilter[0],
							arrFilter[1], nodeLevel, levelDown);
					_setDefaultLevelDown(arrFilter[0], arrFilter[2]);
				}
			}
		}
	}

	/**
	 * 设置树刷新时的DcTree的参数信息
	 *    参数信息包括operatorId,rowid,
	 * @throws ErrorMessage 
	 */
	private void _setRefreshDcParam() throws ErrorMessage{
		if(this.params.getByKey("callback")!=null){
			//分割多个callback
			String[] arrCallbacks = this.params.getByKey("callback").split("~");
			String[] arrcallback = null;
			String[] dcParam = null;
			for(int i=0;i<arrCallbacks.length;i++){
				arrcallback = arrCallbacks[i].split(":");
				if(arrcallback.length >= 5){
					if(arrcallback[4]!=null && !"".equals(arrcallback[4].trim())){
						dcParam = arrcallback[4].split("#");
					}
					dcParmas.put(TOOLS.stringToInt(arrcallback[0]), dcParam);
				}
			}
		}
	}

	/**
	 * 设置树刷新时取树节点文本的OperatorId参数信息
	 *    参数信息包括treeIndex,operatorId,rowid
	 * @throws ErrorMessage 
	 */
	private void _setRefreshTextOpreatorIdParam() throws ErrorMessage{
		if(this.params.getByKey("callback")!=null){
			//分割多个callback
			String[] arrCallbacks = this.params.getByKey("callback").split("~");
			/**以树索引为第一个参数的字符串数组*/
			String[] arrcallback = null;
			String[] textOperatorIdParam = null;//节点取文本操作的operatorId
			for(int i=0;i<arrCallbacks.length;i++){
				arrcallback = arrCallbacks[i].split(":");
				if(arrcallback.length >= 6){
					if(arrcallback[5]!=null && !"".equals(arrcallback[5].trim())){
						textOperatorIdParam = arrcallback[5].split("<");
						_setRefreshTextOperatorParam(arrcallback[0], textOperatorIdParam);
					}
				}else{
					throw new ErrorMessage("TreeBase _setRefreshTextOpreatorIdParam() Error,param TextOperatorId is not correct");
				}
			}
		}
	}

	/**
	 * 设置取树节点文本的OperatorId参数信息
	 * @param treeIndex 树索引
	 * @param textOperatorIdParam operatorType#operatorId
	 * @throws ErrorMessage 
	 */
	private void _setRefreshTextOperatorParam(String treeIndex,String[] textOperatorIdParam) throws ErrorMessage{
		if(textOperatorIdParam!=null){
			String [] operatorId = null;
			for(String textparam:textOperatorIdParam){
				if(textparam!=null){
					operatorId = textparam.split("#");
					if(operatorId!=null && operatorId.length>=2){
						setNodeTextOperatorId(treeIndex, operatorId[0], operatorId[1]);
					}
				}
			}
		}
	}

	/**
	 * 设置树刷新时取树右键的自定义参数信息
	 *    参数信息包括treeIndex,key,value
	 * @throws ErrorMessage 
	 */
	private void _setRefreshRmParam() throws ErrorMessage{
		if(this.params.getByKey("hdp")!=null){
			String [] cps = this.params.getByKey("hdp").split("~");
			for(String cp:cps){
				if(cp!=null && cp.split(":").length>=3){
					putSubTreeParam(TOOLS.stringToInt(cp.split(":")[0]), cp.split(":")[1], cp.split(":")[2]);
				}
			}
		}
	}

	/**
	 * 设置默认展开级别
	 * @param treeIndex
	 * @param leveDown
	 * @throws ErrorMessage 
	 */
	private void _setDefaultLevelDown(String treeIndex,String dLeveDown) throws ErrorMessage{
		if(defualtLevelDown == null){
			defualtLevelDown = new KvMap<String, String>();
		}
		defualtLevelDown.put(treeIndex, dLeveDown);
	}

	/**
	 * 设置树刷新时是否显示右键
	 * @throws ErrorMessage 
	 */
	private void _setRefreshShowRightMenu() throws ErrorMessage{
		if(this.params.getByKey("srm")!=null){
			this.showRightMenu = Boolean.parseBoolean(this.params.getByKey("srm"));
		}
	}

	/**
	 * 设置树刷新时是否显示复选框
	 */
	private void _setRefreshShowCheckBox(){
		if(this.params.getByKey("sck")!=null){
			this.showCheckBox = Boolean.parseBoolean(this.params.getByKey("sck"));
		}
	}

	/**
	 * 设置树刷新时需要展开的节点
	 * @throws ErrorMessage 
	 */
	private void _setsetRefreshExtendNode() throws ErrorMessage{
		if(params.getByKey("extendId")!=null){
			extendNodeId = this.params.getByKey("extendId");
			extendClick = TOOLS.stringToBoolean(params.getByKey("extendClick"));
		}else{
			throw new ErrorMessage("when refresh the tree ,extendNodeId is null!");
		}
	}


	/**
	 * 生成右键菜单
	 * 右键菜单按照节点操作类型来分，及一个节点操作类型对应一个右键菜单对象
	 * @TreeNew mTree 树模版对象
	 * @throws ErrorMessage 
	 */
	private void getRightMenu(TreeNew mTree) throws ErrorMessage{
		ArrayList<RightMenuMeta> rightMenuMetas = null;
		Iterator<Entry<Integer,ArrayList<RightMenuMeta>>> it = kvRightMenuMetas.iterator();
		Entry<Integer,ArrayList<RightMenuMeta>> et = null; 
		while(it.hasNext()){
			et = it.next();
			rightMenuMetas = et.getValue();
			if(rightMenuMetas!=null){
				/**右键名称*/
				String rmName = null;
				/**循环右键的节点操作类型，生成右键菜单信息*/
				for(String operatorType:operatorTypesRm){
					rmName = TOOLS.getId();
					generateRightMenu(rightMenuMetas,operatorType, rmName,mTree,et.getKey());
				}
			}
		}
	}

	/**
	 * 生成右键菜单（一个节点操作类型对应一个右键菜单）
	 * @param rightMenuMetas 右键项对象,存有右键项aciontid,右键项名称
	 * @param operatorType 节点操作类型
	 * @param rmName 右键名称
	 * @param mTree 树模版对象，用于生成树的显示htmlwindwow
	 * @param treeIndex  树编号
	 * @throws ErrorMessage 
	 */
	private void generateRightMenu(ArrayList<RightMenuMeta> rightMenuMetas,
			String operatorType,
			String rmName,
			TreeNew mTree,
			int treeIndex) throws ErrorMessage{
		/**定义当前节点操作类型的右键菜单*/
		RightMenu rm = new RightMenu(rmName,null);
		HtmlWindow itemsRm = null;
		int i = 1;
		for(RightMenuMeta rmm:rightMenuMetas){
			if(operatorType.equals(rmm.getOperatorType())){
				/**设置右键菜单项*/
				itemsRm = rm.getRmChild(
						TOOLS.intToString(i),							//右键菜单项编号
						CaptionComp.get(mUser,rmm.getText()),			//菜单项名称
						"treeS('"+rmm.getActionId()+"','"+rmName+"')"	//菜单项绑定的脚本
				);
//				rm.set(itemsRm);
				mTree._setRightMenuItems(itemsRm, treeIndex+operatorType, rmm.getShowCode());
				i++;
			}
		}
		HtmlWindow rmw = rm.get();
		rmw.put(new HtmlDiv(rmw.getID()+"c"));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.OPERATORID_ADD,operatorIdAddNew.getByKey(treeIndex)));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.OPERATORID_MODIFY,operatorIdModify.getByKey(treeIndex)));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.OPERATORID_DELETE,operatorIdDelete.getByKey(treeIndex)));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.TABLE_NAME,treeDcs.getByKey(treeIndex).getTableName()));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.NODE_TYPE,TOOLS.intToString(treeIndex)));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.TREE_PCID,pcId));
		rmw.put(new HtmlValue(null,"h,"+TreeParam.TREE_AID,aId));
		getRMCustParam(rmw, treeIndex);
		getTextOperatorIdParam(rmw, treeIndex, operatorType);
		mTree._setRightMenu(rmw, treeIndex+operatorType);
	}

	/**
	 * 设置右键的自定义参数
	 * @param rmw
	 * @throws ErrorMessage 
	 */
	private void getRMCustParam(HtmlWindow rmw,int treeIndex) throws ErrorMessage{
		if(rightMenuParam!=null && rightMenuParam.getByKey(treeIndex)!=null){
			ArrayList<String[]> alParam = rightMenuParam.getByKey(treeIndex);
			if(alParam!=null){
				for(int i=0;i<alParam.size();i++){
					rmw.put(new HtmlValue(null,"h,"+alParam.get(i)[0],alParam.get(i)[1]));
				}
			}
		}
	}

	/**
	 * 设置树节点显示operator参数
	 * @param rmw 右键参数
	 * @param treeIndex  树编号
	 * @param operatorType 树节点操作类型
	 * @throws ErrorMessage
	 */
	private void getTextOperatorIdParam(HtmlWindow rmw,int treeIndex,String operatorType) throws ErrorMessage{
		if(nodeTextOperators!=null && nodeTextOperators.getByKey(TOOLS.intToString(treeIndex))!=null){
			KvMap<String,String> nodeTextOperator = nodeTextOperators.getByKey(TOOLS.intToString(treeIndex));
			if(nodeTextOperator!=null){
				rmw.put(new HtmlValue("h,"+TreeParam.NODE_TEXT_OPEERATORID,
						"h,"+TreeParam.NODE_TEXT_OPEERATORID,
						nodeTextOperator.getByKey(operatorType)));
			}
		}
	}

	/**
	 * 设置取树节点的名称、中文名、说明信息的operatorId
	 * @param nodeType 可用此右键菜单项的节点类型
	 * @param operatorId 通过此id查询树节点的名称、中文名、说明信息
	 * @throws ErrorMessage 
	 */
	private void setNodeTextOperatorId(String treeIndex,
			String operatorType,
			String operatorId) throws ErrorMessage{
		TOOLS.checkNull(treeIndex, "TreeBase setNodeTextOperatorId(String nodeType,String operatorId) error,nodeType");
		TOOLS.checkNull(operatorId, "TreeBase setNodeTextOperatorId(String nodeType,String operatorId) error,operatorId");
		if(nodeTextOperators == null){
			nodeTextOperators = new KvMap<String, KvMap<String,String>>();
		}
		KvMap<String,String> nodeTextOperator = nodeTextOperators.getByKey(treeIndex);
		if(nodeTextOperator==null){
			nodeTextOperator = new KvMap<String, String>();
		}
		nodeTextOperator.put(operatorType, operatorId);
		nodeTextOperators.put(treeIndex, nodeTextOperator);
	}

	/**
	 * 设置单棵树是否显示虚根
	 */
	private void _setVirRoot(){
		String virRoot = params.getByKey("virRoot");
		String virExtent = params.getByKey("virRootExt");
		if("Y".equals(virRoot)){
			showVirRoot = true;
		}
		if("Y".equals(virExtent)){
			isVirExtend = true;
		}
	}

	/**
	 * 清理参数
	 */
	private void clearParams(){
		clearParam(params, "tId");
		clearParam(params, "aId");
		clearParam(params, "srm");
		clearParam(params, "sck");
		clearParam(params, "bmType");
		clearParam(params, "extendId");
		clearParam(params, "extendNodeLevel");
		clearParam(params, ".customerParam");
		clearParam(params, "isFilterByOperator");
		clearParam(params, "callback");
		clearParam(params, "filter");
		clearParam(params, "refreshVc");
		clearParam(params, "pcid");
	}

	/**
	 * 清理params容器不再用的参数
	 * @param params 需要清理的容器 
	 * @param key 需要清理的参数名
	 */
	private void clearParam(KvMap<String,String> params,String key){
		if(params!=null && params.containsKey(key)){
			params.removeByKey(key);
		}
	}

	/**
	 * 取索引树的过滤operatorId
	 * @param treeDc 树的Dc
	 * @throws ErrorMessage
	 */
	private void getTreeIndexFilter(TreeDC treeDc) throws ErrorMessage{
		if(Tree_DC_Type.TreeIndex.equals(treeDc.getType()) &&
				((TreeDcIndex)treeDc).getFilterOperatorId()!=null){
			this.filterOperatorId = ((TreeDcIndex)treeDc).getFilterOperatorId();
		}
	}

	/**
	 * 设置索引树的过滤operatorId
	 * @param treeDc
	 * @throws ErrorMessage
	 */
	private void setTreeIndexFilter(TreeDC treeDc) throws ErrorMessage{
		if(Tree_DC_Type.TreeIndex.equals(treeDc.getType()) && !TOOLS.StringIsEmpty(this.filterOperatorId)){
			((TreeDcIndex)treeDc).setFilterOperatorId(this.filterOperatorId);
		}
	}

	/**
	 * 判断参数中是否包含特殊字符
	 * @param str
	 * @throws ErrorMessage 
	 */
	private void checkString(String str) throws ErrorMessage{
		String[] flag = new String[]{"#",":","~","<"};
		if(str!=null){
			for(String s:flag){
				if(str.indexOf(s)!=-1){
					throw new ErrorMessage("TreeBase put...Param("+str+") have illegal code("+s+").");
				}
			}
		}
	}

}
